The ENET Shim opens when an Open Slot call is made to open the Ethernet driver in NuBus slot 0. The shim intercepts this request and loads a .ENET driver entry into the driver table. From that time, applications which call OpenDriver will get the driver reference number for the shim driver, which then handles the various Control calls it receives.
Note that the shim only works for the built-in Ethernet device, not for an installed PCI Ethernet card.
The following sequence of calls works for all Ethernet connections in which Open Transport is present:
/* File: ShowOTEnetAddr.c Contains: Simple app to print out Ethernet addresses for any Ethernet card on any Mac which has Open Transport installed. This includes the PCI based Macs. Copyright: © 1993-1995 by Apple Computer, Inc., all rights reserved. Change History (most recent first): 2/6/96 rkubota (1) initialized the index variable to 0 in main To Do: */ #include#include #include #include #include #include // open transport files #include struct Address8022 { OTAddressType fAddrFamily; UInt8 fHWAddr[k48BitAddrLength]; UInt16 fSAP; UInt8 fSNAP[k8022SNAPLength]; }; typedef struct Address8022 Address8022; #define kTrue 1 #define kFalse 0 //------------------------------------------------------------------------------- ---------- // Globals //------------------------------------------------------------------------------- ---------- EndpointRef gEndpoint1; //------------------------------------------------------------------------------- ---------- // prototypes //------------------------------------------------------------------------------- ---------- OSStatus DoBind(void); OSStatus GetEthernetAddress(char *slotName); /******************************************************************************* ** DoBindENET For this sample, we need to bind to any ethernet endpoint. In this case we bind to enet protocol type 0x8888. We use an Address8022 variable type for expediency ********************************************************************************/ OSStatus DoBind() { OSStatus osStatus; TBind gRequestInfo; Address8022 theAddr = {AF_8022, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0x8888, {0x00,0x00,0x00,0x00,0x00}}; // finish bind information gRequestInfo.addr.buf = (UInt8 *)&theAddr; gRequestInfo.addr.len = 10; // family type + Ethernet + type field // don't use sizeof(theAddr) since we are binding to type 1 Ethernet // address, not to an 802.2 address. gRequestInfo.addr.maxlen = 0; gRequestInfo.qlen = 0; if (osStatus = OTBind(gEndpoint1, &gRequestInfo, NULL)) { printf("\nCould not bind an endpoint, error = %d\n", osStatus); CloseOpenTransport(); return -4; } return osStatus; } /******************************************************************************* ** GetEthernetAddress ********************************************************************************/ OSStatus GetEthernetAddress(char *slotName) { OSStatus osStatus; TBind returnInfo; Address8022 theReturnAddr = {AF_8022, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0x0000, {0x00,0x00,0x00,0x00,0x00}}; returnInfo.addr.buf = (UInt8 *)&theReturnAddr; returnInfo.addr.maxlen = 10; // family type + 6 bytes for Ethernet + type returnInfo.qlen = 0; osStatus = OTGetProtAddress(gEndpoint1,&returnInfo,NULL); if (osStatus == kOTNoError) { if (slotName[0] != 0x00) printf("\nAddress for PCI Slot %s => ", slotName); else printf("\nAddress for Ethernet Built-In => "); printf("%02x.",(int )theReturnAddr.fHWAddr[0]); printf("%02x.",(int )theReturnAddr.fHWAddr[1]); printf("%02x.",(int )theReturnAddr.fHWAddr[2]); printf("%02x.",(int )theReturnAddr.fHWAddr[3]); printf("%02x.",(int )theReturnAddr.fHWAddr[4]); printf("%02x",(int )theReturnAddr.fHWAddr[5]); } else printf("\n\nCould not get the Ethernet address, error = %d\n\n", osStatus); return osStatus; } /******************************************************************************* ** main ********************************************************************************/ main() { OSStatus osStatus; OTPortRecord devicePortRecord; Boolean foundAPort; UInt32 index; printf("\n\nEthernet Address Display v1.1\n"); printf("\nThis application displays the Ethernet address for the\n"); printf("Ethernet Built-In port and PCI Ethernet cards.\n\n"); if (osStatus = InitOpenTransport()) { printf("\n\nOpen Transport is not installed!\n\n"); return 0; } index = 0; // iterate thru each OT port record for ethernet ports. while (foundAPort = OTGetIndexedPort(&devicePortRecord,index)) { if ((devicePortRecord.fCapabilities & kOTPortIsDLPI) && (devicePortRecord.fCapabilities & kOTPortIsTPI) && (kOTEthernetDevice == OTGetDeviceTypeFromPortRef(devicePortRecord.fRef))) { gEndpoint1 = OTOpenEndpoint(OTCreateConfiguration(devicePortRecord.fPortName), (OTOpenFlags)NULL, NULL,&osStatus); if (osStatus == kOTNoError) { // we have to bind the endpoint before we can get it's address info osStatus = DoBind(); if (osStatus == kOTNoError) { GetEthernetAddress(devicePortRecord.fSlotID); OTUnbind(gEndpoint1); } OTCloseProvider(gEndpoint1); } } index++; } // closing down CloseOpenTransport(); printf("\n\nTo quit the application press Command-Q.\n"); return 0; }